package com.shisan.tingshu.search.config;

import org.redisson.Redisson;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;


@Configuration
public class RedissonAutoConfiguration {

    Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private RedisProperties redisProperties;

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 定义Redisson客户端的Bean对象
     */
    @Bean
    public RedissonClient redissonClient() {

        // 给Redisson设置配置信息
        Config config = new Config();
        config.useSingleServer() // 使用单机模式
                .setPassword(redisProperties.getPassword())
                .setAddress("redis://" + redisProperties.getHost() + ":" + redisProperties.getPort());
        // 创建Redisson客户端
        RedissonClient redissonClient = Redisson.create(config);

        return redissonClient;
    }

    /**
     * 定义一个BloomFilter的Bean对象
     */
    @Bean
    public RBloomFilter rBloomFilter(RedissonClient redissonClient) {

        // 如果在Redis中没有这个key，那么会自动创建，并返回这个key对应的布隆过滤器对象。反之 直接返回已经创建好的布隆过滤器
        // tryInit()方法返回true表示初始化成功（即之前不存在，现在新创建了），返回false表示已经存在（即之前已经初始化过）
        RBloomFilter<Object> albumIdBloomFilter = redissonClient.getBloomFilter("albumIdBloomFilter");
        // 加个锁，让分布式布隆过滤器只初始化一次且同步数据只做一次
        // 当锁存在的时候，表示布隆过滤器已经初始化过了，直接返回布隆过滤器对象
        String bloomFilterLockKey = "albumIdBloomFilter:lock";
        Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent(bloomFilterLockKey, "1");
        if (aBoolean) {
            // 初始化布隆过滤器
            boolean b = albumIdBloomFilter.tryInit(1000000l, 0.001);  // 利用分布式锁保证分布式布隆的初始化只做一次
            if (b) {
                logger.info("成功创建新的布隆过滤器，等待数据填充");
            } else {
                logger.info("布隆过滤器已存在，直接使用");
            }
        }

        return albumIdBloomFilter;
    }
}